#pragma once

#include "Socket.hpp"
#include "TcpServer.hpp"
#include "Util.hpp"
#include "Log.hpp"
#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <unordered_map>

using namespace SocketModule;
using namespace LogModule;

const std::string gspace = " ";
const std::string glinespace = "\r\n";
const std::string glinesep = ": ";

const std::string webroot = "./wwwroot";
const std::string homepage = "index.html";
const std::string page_404 = "/404.html";

class HttpRequest
{
public:
    HttpRequest() : _is_interact(false)
    {
    }

    std::string Serialize()
    {
        return std::string();
    }
    void ParseReqLine(std::string &reqline)
    {
        // GET / http/1.1
        std::stringstream ss(reqline);
        ss >> _method >> _uri >> _version;
    }
    bool Deserialize(std::string &reqstr)
    {
        // 1.提取请求行
        // 要提取完整的一行，所以
        std::string reqline;
        bool res = Util::ReadOneLine(reqstr, &reqline, glinespace); // 需要找到第一行
        LOG(LogLevel::DEBUG) << reqline;

        // std::cout<<reqstr;
        //  2. 对请求行进行反序列化
        ParseReqLine(reqline);

        if (_uri == "/")
        {
            _uri = webroot + _uri + homepage; // ./wwwroot/index.html
        }
        else
        {
            _uri = webroot + _uri; // ./wwwroot/a/b/c.html
        }
        LOG(LogLevel::DEBUG) << "_method: " << _method;
        LOG(LogLevel::DEBUG) << "_uri: " << _uri;
        LOG(LogLevel::DEBUG) << "_version: " << _version;
        const std::string temp = "?";
        auto pos = _uri.find(temp);
        if (pos == std::string::npos)
        {
            return true;
        }

        // 到这里就说明不是普通的请求
        //_uri: ./wwwroot/login.html?username=1&password=1
        _args = _uri.substr(pos + temp.size());
        _uri = _uri.substr(0, pos);
        _is_interact = true;

        return true;
    }
    std::string Uri() { return _uri; }
    bool IsInteract()
    {
        return _is_interact;
    }
    std::string Args()
    {
        return _args;
    }
    ~HttpRequest() {}

private:
    std::string _method;
    std::string _uri;
    std::string _version;

    std::unordered_map<std::string, std::string> _headers;
    std::string _blankline;
    std::string _text;

    std::string _args;
    bool _is_interact;
};

class HttpResponse
{
public:
    HttpResponse() : _blankline(glinespace) // glinespace 拼成了gspace
    {
    }
    // http，不要依赖第三方库去做序列化
    std::string Serialize()
    {
        std::string status_line = _version + gspace + std::to_string(_code) + gspace + _desc + glinespace;
        std::string resp_handle;
        for (auto &header : _headers)
        {
            std::string line = header.first + glinesep + header.second + glinespace;
            resp_handle += line;
        }
        return status_line + resp_handle + _blankline + _text;
    }
    void SetTargetFile(const std::string &target)
    {
        _targetfile = target;
    }
    void SetCode(int code)
    {
        _code = code;
        switch (_code)
        {
        case 200:
            _desc = "OK";
            break;
        case 404:
            _desc = "Not Found";
            break;
        case 302:
            _desc = "See Other";
            break;
        case 301:
            _desc = "Move Permanently";
            break;
        default:
            break;
        }
    }
    void SetHeader(const std::string &key, const std::string &value)
    {
        if (_headers.find(key) != _headers.end()) // 如果已经有了当前的kv，不插入
        {
            return;
        }
        else
        {
            _headers.insert(std::make_pair(key, value));
        }
    }

    std::string UriToSuffix(std::string &targetname)
    {
        auto pos = targetname.rfind(".");
        if (pos == std::string::npos)
        {
            return "text/html";
        }
        std::string suffix = targetname.substr(pos);
        if (suffix == ".html" || suffix == ".htm")
        {
            return "text/html";
        }
        else if (suffix == ".jpg")
            return "image/jpeg";
        else if (suffix == ".png")
            return "image/jpeg";
        else
            return "";
    }

    bool MakeResponse()
    {
        bool res = Util::ReadFileContent(_targetfile, &_text); // 浏览器请求的资源，一定会存在吗？出错呢？
        if (_targetfile == "./wwwroot/redir_test")             // 请求这个文件的时候去做重定向
        {
            SetCode(302);
            SetHeader("Location", "https://www.qq.com");
            return true;
        }

        if (!res)
        {
            LOG(LogLevel::WARING) << "client want get : " << _targetfile << "buf not found";
            // 1.设置状态码
            SetCode(404);
            // SetHeaders()
            // 2.客户端重新访问，修改路径
            _targetfile = webroot + page_404;           // 更改文件路径
            Util::ReadFileContent(_targetfile, &_text); // 重新再去访问一次，可以用重定向
            // 3.设置kv属性值
            std::string suffix = UriToSuffix(_targetfile);
            SetHeader("Content-Type", suffix);

            int filesize = Util::GetFileSize(_targetfile);
            SetHeader("Content-Length", std::to_string(filesize));

            // // 重定向操作
            // SetCode(302);
            // SetHeader("Location", "http://47.120.48.126:8080/404.html"); // 重定向到404的界面
            // return true;
        }
        else
        {
            SetCode(200);
            std::string suffix = UriToSuffix(_targetfile);
            SetHeader("Content-Type", suffix);
            int filesize = Util::GetFileSize(_targetfile);
            SetHeader("Content-Length", std::to_string(filesize));
        }
        return true;
    }

    void SetText(std::string &t)
    {
        _text = t;
    }

    bool Deserialize(std::string &reqstr)
    {
        return true;
    }
    ~HttpResponse() {}
    // private:
    std::string _version;
    int _code;         // 404
    std::string _desc; // 比如404 Not Found

    std::unordered_map<std::string, std::string> _headers;
    std::string _blankline;
    std::string _text;

    std::string _targetfile;
};

using http_func_t = std::function<void(HttpRequest &req, HttpResponse &resp)>;

class Http
{
public:
    Http(uint16_t port) : tsvrp(std::make_unique<TcpServer>(port))
    {
    }
    void HandleHttpRequest(std::shared_ptr<Socket> &sock, InetAddr &client)
    {
        // 收到请求
        std::string httpreqstr;
        // tcp的读是面向字节流的，所以不一定读到的完整的报文
        int n = sock->Recv(&httpreqstr);
        if (n > 0)
        {
            // 对报文的完整性进行审核
            HttpRequest req;
            HttpResponse resp;

            req.Deserialize(httpreqstr); // 反序列化，提取请求行
            resp._version = "HTTP/1.1";
            if (req.IsInteract())        // 不是静态，需要交互
            {
                if (_route.find(req.Uri()) == _route.end())
                {
                    // SetCode(302);
                }
                else
                {
                    _route[req.Uri()](req, resp); // resp是输出型参数，这里得到一个应答，进行序列化后发送

                    std::string response_str = resp.Serialize();
                    sock->Send(response_str);
                }
            }
            else
            {
                resp.SetTargetFile(req.Uri());

                if (resp.MakeResponse())
                {
                    std::string response_str = resp.Serialize();
                    sock->Send(response_str);
                }
            }

            // resp._code = 200; // 表示请求成功
            // resp._desc = "OK";

            // bool res = Util::ReadFileContent(filename, &(resp._text));
            // (void)res;
            // std::string response_str = resp.Serialize();
            // std::cout << __FILE__ << __LINE__ << "response_str: " << response_str << std::endl;
            // sock->Send(response_str);

            // if (resp.MakeResponse())
            // {
            //     std::string response_str = resp.Serialize();
            //     sock->Send(response_str);
            // }
        }

// #ifndef DEBUG
// #define DEBUG
#ifdef DEBUG
        // 收到请求
        std::string httpreqstr;
        // tcp的读是面向字节流的，所以不一定读到的完整的报文
        sock->Recv(&httpreqstr);
        std::cout << "-----------" << httpreqstr;

        // 构建http的应答
        HttpResponse resp;
        resp._version = "HTTP/1.1";
        resp._code = 200; // 表示请求成功
        resp._desc = "OK";
        std::string filename = webroot + homepage;

        bool res = Util::ReadFileContent(filename, &(resp._text));
        (void)res;
        std::cout << __FILE__ << __LINE__ << "resp._text: " << resp._text << std::endl;

        std::string response_str = resp.Serialize();
        std::cout << __FILE__ << __LINE__ << "response_str: " << response_str << std::endl;
        sock->Send(response_str);
#endif
    }
    void Start()
    {
        tsvrp->Start([this](std::shared_ptr<Socket> &sock, InetAddr &client)
                     { this->HandleHttpRequest(sock, client); });
    }
    void RegisterService(const std::string name, http_func_t h)
    {
        std::string key = webroot + name; //./wwwroot/login
        auto iter = _route.find(key);
        if (iter == _route.end())
        {
            _route.insert(std::make_pair(key, h));
        }
    }
    ~Http()
    {
    }

private:
    std::unique_ptr<TcpServer> tsvrp;
    std::unordered_map<std::string, http_func_t> _route; // 路由方法
};

// #pragma once

// #include "Socket.hpp"
// #include "TcpServer.hpp"
// #include "Util.hpp"
// #include "Log.hpp"
// #include <iostream>
// #include <string>
// #include <memory>
// #include <sstream>
// #include <unordered_map>

// using namespace SocketModule;
// using namespace LogModule;

// const std::string gspace = " ";
// const std::string glinespace = "\r\n";
// const std::string glinesep = ": ";

// const std::string webroot = "./wwwroot";
// const std::string homepage = "login.html";
// const std::string page_404 = "/404.html";

// class HttpRequest
// {
// public:
//     HttpRequest() {}

//     std::string Serialize()
//     {
//         return std::string();
//     }
//     void ParseReqLine(std::string &reqline)
//     {
//         // GET / http/1.1
//         std::stringstream ss(reqline);
//         ss >> _method >> _uri >> _version;
//     }
//     bool Deserialize(std::string &reqstr)
//     {
//         // 1.提取请求行
//         // 要提取完整的一行，所以
//         std::string reqline;
//         bool res = Util::ReadOneLine(reqstr, &reqline, glinespace); // 需要找到第一行
//         LOG(LogLevel::DEBUG) << reqline;

//         // std::cout<<reqstr;
//         //  2. 对请求行进行反序列化
//         ParseReqLine(reqline);

//         if (_uri == "/")
//         {
//             _uri = webroot + _uri + homepage; // ./wwwroot/index.html
//         }
//         else
//         {
//             _uri = webroot + _uri; // ./wwwroot/a/b/c.html
//         }
//         LOG(LogLevel::DEBUG) << "_method: " << _method;
//         LOG(LogLevel::DEBUG) << "_uri: " << _uri;
//         LOG(LogLevel::DEBUG) << "_version: " << _version;

//         return true;
//     }
//     std::string Uri() { return _uri; }

//     ~HttpRequest() {}

// private:
//     std::string _method;
//     std::string _uri;
//     std::string _version;

//     std::unordered_map<std::string, std::string> _headers;
//     std::string _blankline;
//     std::string _text;
// };

// class HttpResponse
// {
// public:
//     HttpResponse() : _blankline(glinespace)//glinespace 拼成了gspace
//     {
//     }
//     //http，不要依赖第三方库去做序列化
//      std::string Serialize()
//      {
//          std::string status_line = _version + gspace + std::to_string(_code) + gspace + _desc + glinespace;
//          std::string resp_handle;
//          for(auto &header: _headers)
//          {
//              std::string line = header.first + glinesep + header.second + glinespace;
//              resp_handle += line;
//          }
//          return status_line + resp_handle + _blankline + _text;
//      }
//     void SetTargetFile(const std::string &target)
//     {
//         _targetfile = target;
//     }
//     void SetCode(int code)
//     {
//         _code = code;
//         switch(_code)
//         {
//             case 200:
//                 _desc = "OK";
//                 break;
//             case 404:
//                 _desc = "Not Found";
//                 break;
//             default:
//                 break;
//         }
//     }
//     bool MakeResponse()
//     {
//         bool res = Util::ReadFileContent(_targetfile, &_text); // 浏览器请求的资源，一定会存在吗？出错呢？
//         if (!res)
//         {
//             SetCode(404);
//             _targetfile = webroot + page_404;
//             Util::ReadFileContent(_targetfile,&_text);//重新再去访问一次，可以用重定向
//         }
//         return true;
//     }

//     bool Deserialize(std::string &reqstr)
//     {
//         return true;
//     }
//     ~HttpResponse() {}
//     // private:
//     std::string _version;
//     int _code;         // 404
//     std::string _desc; // 比如404 Not Found

//     std::unordered_map<std::string, std::string> _headers;
//     std::string _blankline;
//     std::string _text;

//     std::string _targetfile;
// };

// class Http
// {
// public:
//     Http(uint16_t port) : tsvrp(std::make_unique<TcpServer>(port))
//     {
//     }
//     void HandleHttpRequest(std::shared_ptr<Socket> &sock, InetAddr &client)
//     {
//         // 收到请求
//         std::string httpreqstr;
//         // tcp的读是面向字节流的，所以不一定读到的完整的报文
//         int n = sock->Recv(&httpreqstr);
//         if (n > 0)
//         {
//             // 对报文的完整性进行审核
//             HttpRequest req;
//             req.Deserialize(httpreqstr); // 反序列化，提取请求行

//             HttpResponse resp;
//             resp.SetTargetFile(req.Uri());

//             resp.MakeResponse();
//             resp._version = "HTTP/1.1";
//             resp._code = 200; // 表示请求成功
//             resp._desc = "OK";

//             // bool res = Util::ReadFileContent(filename, &(resp._text));
//             // (void)res;
//             std::string response_str = resp.Serialize();
//             //std::cout << __FILE__ << __LINE__ << "response_str: " << response_str << std::endl;
//             sock->Send(response_str);

//             // if (resp.MakeResponse())
//             // {
//             //     std::string response_str = resp.Serialize();
//             //     sock->Send(response_str);
//             // }
//         }

// // #ifndef DEBUG
// // #define DEBUG
// #ifdef DEBUG
//         // 收到请求
//         std::string httpreqstr;
//         // tcp的读是面向字节流的，所以不一定读到的完整的报文
//         sock->Recv(&httpreqstr);
//         std::cout << "-----------" << httpreqstr;

//         // 构建http的应答
//         HttpResponse resp;
//         resp._version = "HTTP/1.1";
//         resp._code = 200; // 表示请求成功
//         resp._desc = "OK";
//         std::string filename = webroot + homepage;

//         bool res = Util::ReadFileContent(filename, &(resp._text));
//         (void)res;
//         std::cout << __FILE__ << __LINE__ << "resp._text: " << resp._text << std::endl;

//         std::string response_str = resp.Serialize();
//         std::cout << __FILE__ << __LINE__ << "response_str: " << response_str << std::endl;
//         sock->Send(response_str);
// #endif
//     }
//     void Start()
//     {
//         tsvrp->Start([this](std::shared_ptr<Socket> &sock, InetAddr &client)
//                      { this->HandleHttpRequest(sock, client); });
//     }
//     ~Http()
//     {
//     }

// private:
//     std::unique_ptr<TcpServer> tsvrp;
// };